﻿using System;
using System.Collections.Generic;

using System.Linq;
using System.Data.Entity;
using System.Linq.Expressions;

using AL.Extension;
using System.Collections;

namespace AL.DAL.Base {

    public abstract class BaseDAL<T> where T : class {

        private readonly ContextAL _dataContext;
        protected readonly IDbSet<T> dbset;

        /// <summary>
        /// HH: 构造函数 - 初始化
        /// </summary>
        protected BaseDAL(ContextAL context) {
            _dataContext = context;
            dbset = _dataContext.Set<T>();
        }


        /// <summary>
        /// HH: 直接输入 SQL 语句或者存储过程 动态创建类并返回实例（该方法破坏了架构层级关系，非特殊情况不要使用）
        /// </summary>
        public IEnumerable SqlQueryForDynamic(string sql, params object[] parameters) {
            return _dataContext.Database.SqlQueryForDynamic(sql, parameters);
        }

        #region <  CUD (增删改)基础操作 集合  >

        /// <summary>
        /// HH: 通用 - 新增
        /// </summary>
        public virtual void Create(T entity) {
            dbset.Add(entity);
            _dataContext.SaveChanges();
        }
        /// <summary>
        /// HH: 通用 - 修改
        /// </summary>
        public virtual void Update(T entity) {
            dbset.Attach(entity);
            _dataContext.Entry(entity).State = System.Data.EntityState.Modified;
            _dataContext.SaveChanges();
        }
        /// <summary>
        /// HH: 通用 - 删除
        /// </summary>
        public virtual void Delete(T entity) {
            dbset.Attach(entity); // 有时候直接删除不成功，必须附加此句
            dbset.Remove(entity);
            _dataContext.SaveChanges();
        }
        /// <summary>
        /// HH: 通用 - 根据条件删除
        /// </summary>
        public virtual void Delete(Expression<Func<T, bool>> where) {
            IEnumerable<T> objects = dbset.Where<T>(where).AsEnumerable();
            foreach (T obj in objects)
                dbset.Remove(obj);

            _dataContext.SaveChanges();
        }

        #endregion


        #region <  Retrieve (查询)基础操作 集合  >

        /// <summary>
        /// HH: 根据主键ID 获取一个对象（主键ID为整数类型）
        /// </summary>
        public virtual T GetById(long id) {
            return dbset.Find(id);
        }
        /// <summary>
        /// HH: 根据主键ID 获取一个对象（主键ID为字符串类型）
        /// </summary>
        public virtual T GetById(string id) {
            return dbset.Find(id);
        }
        /// <summary>
        /// HH: 根据 lambda 条件表达式 获取一个对象
        /// </summary>
        /// <param name="where">lambda 条件表达式</param>
        public T Get(Expression<Func<T, bool>> where) {
            return dbset.AsNoTracking().Where(where).FirstOrDefault<T>();
        }


        /// <summary>
        /// HH: 获取所有 IEnumerable 公开枚举器支持的指定类型的集合
        /// </summary>
        public virtual IEnumerable<T> GetAll() {
            return dbset.AsNoTracking().ToList();
        }
        /// <summary>
        /// HH: 获取指定条件的 IEnumerable 公开枚举器支持的指定类型的集合
        /// </summary>
        /// <param name="where">lambda 条件表达式</param>
        public virtual IEnumerable<T> GetMany(Expression<Func<T, bool>> where) {
            return dbset.AsNoTracking().Where(where).ToList();
        }


        /// <summary>
        /// HH: 获取所有 Queryable 可操作数据源集合 （提供对数据类型已知的特定数据源的查询进行计算的功能）
        /// </summary>
        public virtual IQueryable<T> GetQueryAll() {
            return dbset;
        }
        /// <summary>
        /// HH: 获取指定条件的 Queryable 可操作数据源集合 （提供对数据类型已知的特定数据源的查询进行计算的功能）
        /// </summary>
        /// <param name="where">lambda 条件表达式</param>
        public virtual IQueryable<T> GetQueryMany(Expression<Func<T, bool>> where) {
            return dbset.Where(where);
        }

        #endregion



        #region <  分页查询操作 集合  >

        /// <summary>
        /// HH: 基于 IEnumerable 的基础分页方法（单个条件，排序传入字段的字符串）
        /// </summary>
        public IEnumerable<T> PageList(string orderBy, bool isAsc, Expression<Func<T, bool>> where, int pageIndex, int pageSize, out int rowsCount) {
            IQueryable<T> list = this.dbset.OrderBy(orderBy, (isAsc ? OrderByType.Asc : OrderByType.Desc)).Where(where);

            rowsCount = list.Count();
            return list.Skip(pageSize * (pageIndex - 1)).Take(pageSize);
        }

        /// <summary>
        /// HH: 分页获取信息条目（单个条件）
        /// </summary>
        /// <param name="isAsc"></param>
        /// <param name="where">筛选条件</param>
        /// <param name="pageIndex">页索引</param>
        /// <param name="pageSize">页大小</param>
        /// <param name="rowsCount">返回 总记录数</param>
        /// <param name="orderBy"></param>
        public IEnumerable<T> PageList<TKey>(Expression<Func<T, TKey>> orderBy, bool isAsc, Expression<Func<T, bool>> where, int pageIndex, int pageSize, out int rowsCount) {
            IQueryable<T> list;
            if (isAsc) {
                list = this.dbset.OrderBy(orderBy).Where(where);
            } else {
                list = this.dbset.OrderByDescending(orderBy).Where(where);
            }

            rowsCount = list.Count();
            return list.Skip(pageSize * (pageIndex - 1)).Take(pageSize);
        }

        #endregion













    }
}
